﻿using BusinessLogic;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Utity;

public class OrmParse
{
    public JToken ReturnToken()
    {
        JsonLogic bll = JsonLogic.Instance;
        JToken jsonRows = null;
        DataTable dsetOvum = QueryLinkOvumData();
        if (HostData == null)
        {
            DataTable dtbl = dsetOvum;
            dtbl = bll.PagationCloneDataTable(dtbl, GetParamValues);
            jsonRows = JToken.FromObject(dtbl);
        }
        else {
            //jsonRows = MergeLinkData(dsetOvum);
        }

        
        //OrmParse.ReleaseCache();
        return jsonRows;
    }

    /// <summary>
    /// 对单条JToken增加LINK属性
    /// </summary>
    /// <returns></returns>
    void MakeOvumToken(JToken rowToken,DataTable dtblOvum)
    {
        string aliasNamed = GetAliasNamed;
        List<string> lstFilter = new List<string>();
        Dictionary<string, string> linkKey = GetLinkKeys;
        foreach (string key in linkKey.Keys)
        {
            lstFilter.Add(string.Format("[{0}]='{1}'", linkKey[key], rowToken.Value<string>(key)));
        }
        dtblOvum.DefaultView.RowFilter = string.Join(" AND ", lstFilter.ToArray());
        DataTable dtblFiltered = dtblOvum.DefaultView.ToTable();
        if (dtblFiltered.Rows.Count > 1)
        {
            rowToken[aliasNamed] = JToken.FromObject(dtblFiltered);
        }
        else if (dtblFiltered.Rows.Count == 1)
        {
            DataRow drowFiltered = dtblFiltered.Rows[0];
            foreach (DataColumn dc in drowFiltered.Table.Columns)
            {
                rowToken[aliasNamed][dc.ColumnName] = new JValue(drowFiltered[dc]);
            }
        }

        if (dtblFiltered.Rows.Count > 0 && this.GetNode["LINK"] != null && this.GetNode["LINK"].HasValues)
        {
            var aliasNamedToken = rowToken[aliasNamed];
            if (aliasNamedToken is JObject)
            {
                OrmParse parse = new OrmParse();
                parse.GetParamValues = this.GetParamValues;
                parse.GetRoot = this.GetRoot;
                parse.GetNode = this.GetNode["LINK"];
                parse.HostData = dtblOvum;
                parse.MakeOvumToken(aliasNamedToken, null);
            }
            else if (aliasNamedToken is JArray)
            {
                foreach (var token in aliasNamedToken)
                {
                    OrmParse parse = new OrmParse();
                    parse.GetParamValues = this.GetParamValues;
                    parse.GetRoot = this.GetRoot;
                    parse.GetNode = this.GetNode["LINK"];
                    parse.HostData = dtblOvum;
                    parse.MakeOvumToken(token, null);
                }
            }
        }
    }


    #region 解析LINK_KEY的筛选条件
    Dictionary<string, string> GetLinkKeys
    {
        get
        {
            string strLinkKey = GetConfigNode.Value<string>("LINK_KEY");
            Regex reg = new Regex(@"(\w+)\|*(\w*)");
            Dictionary<string, string> d = new Dictionary<string, string>();
            if (reg.IsMatch(strLinkKey))
            {
                MatchCollection ms = reg.Matches(strLinkKey);
                foreach (Match m in ms)
                {
                    if (m.Success)
                    {
                        string key = m.Groups[1].Value;
                        string value = key;
                        if (m.Groups.Count > 2)
                        {
                            value = m.Groups[2].Value;
                        }
                        d[key] = value;
                    }
                }
                return d;
            }
            else
            {
                return null;
            }
        }
    }

    /// <summary>
    /// 解析LINK_KEY的筛选条件
    /// </summary>
    /// <returns></returns>
    Dictionary<string, string> ReturnFilterParams()
    {
        if (HostData != null)
        {
            Dictionary<string, string> dicFilter = new Dictionary<string, string>();
            Dictionary<string, string> d = GetLinkKeys;
            foreach (string key in d.Keys)
            {
                DataTable dtblDisinct = HostData.DefaultView.ToTable(true, key);
                List<string> lst = new List<string>();
                foreach (DataRow drow in dtblDisinct.Rows)
                {
                    if (drow.Table.Columns[0].DataType.Equals(typeof(string)) && GetRuntimeType() == "table")
                    {
                        lst.Add(string.Format("'{0}'", drow[0]));
                    }
                    else
                    {
                        lst.Add(string.Format("{0}", drow[0]));
                    }
                }
                dicFilter[d[key]] = string.Join(",", lst.ToArray());
            }
            return dicFilter;
        }
        else {
            return null;
        }
    }
    #endregion

    #region 缓存操作
    private static ParamterSet dataCache = new ParamterSet();
    public static void ReleaseCache()
    {
        dataCache = new ParamterSet();
    }

    public static void AddCache(string sid, DataTable dtbl)
    {
        dataCache.SetValue(sid, dtbl);
    }

    #endregion

    #region 获取关联表(虫子)的数据
    public DataTable QueryLinkOvumData()
    {
        if (GetNode["SID"] != null)
        {
            string sid = GetNode.Value<string>("SID");
            return dataCache.GetValue<DataTable>(sid);
        }
        else
        {
            JsonLogic bll = JsonLogic.Instance;
            if (!string.IsNullOrWhiteSpace(GetDbName))
            {
                GetParamValues["DB_NAME"] = GetDbName;
            }
            DataSet dsetOvum = null;
            var dicFilter = ReturnFilterParams();
            if (GetRuntimeType() == "sp")
            {
                GetParamValues["SP_NAME"] = SqlDynamicSelect();
                if (dicFilter != null)
                {
                    foreach (string key in dicFilter.Keys)
                    {
                        GetParamValues[key] = dicFilter[key];
                    }
                }
                dsetOvum = bll.GetDataSet(GetParamValues);
            }
            else if (GetRuntimeType() == "sql")
            {
                GetParamValues["SP_NAME"] = "@" + SqlDynamicSelect();
                if (dicFilter != null)
                {
                    foreach (string key in dicFilter.Keys)
                    {
                        GetParamValues[key] = dicFilter[key];
                    }
                }
                dsetOvum = bll.QueryDataSetAsText(GetParamValues);
            }
            else
            {
                string sql = SqlDynamicSelect();
                if (dicFilter != null)
                {
                    foreach (string key in dicFilter.Keys)
                    {
                        sql += string.Format(" AND [{0}] in ({1})", key, dicFilter[key]);
                    }
                }
                GetParamValues["SP_NAME"] = sql;
                dsetOvum = bll.QueryDataSetAsText(GetParamValues);
            }
            this.SelectedEffectRows = bll.SelectedEffectRows;
            DataTable dtblOvum = dsetOvum.Tables[0];
            string sid = Guid.NewGuid().ToString().Replace("-", "");
            OrmParse.AddCache(sid, dtblOvum);
            GetNode["SID"] = new JValue(sid);
            return dtblOvum;
        }
    }

    /// <summary>
    /// 获取关联表Sql语句
    /// </summary>
    /// <returns></returns>
     string SqlDynamicSelect()
    {
        var node = GetNode;
        string _where = "";
        string or_sp_name = node.Value<string>("SP_NAME");
        string sp_name = GetRuntimeName();
        if (sp_name.Length == 0)
        {
            throw new NullReferenceException("Dynamic select name not set");
        }
        if (GetRuntimeType() != "table")
        {
            return sp_name;
        }
        List<string> arrWhere = new List<string>();
        arrWhere.Add("1 = 1 ");
        if (node["WHERE_CONDITION"] != null)
        {
            JArray arrCondition = node["WHERE_CONDITION"].Value<JArray>();
            foreach (var p in arrCondition)
            {
                string ret = GetWhereJointString(p);
                if (!string.IsNullOrEmpty(ret))
                {
                    arrWhere.Add(ret);
                }
            }
        }
        _where = "WHERE " + string.Join(" AND ", arrWhere.ToArray());
        return GetSelectSqlString(node, sp_name) + "\r\n" + _where;
    }

    /// <summary>
    /// Select Fields拼接
    /// </summary>
    /// <param name="parentToken"></param>
    /// <param name="table_name"></param>
    /// <returns></returns>
    string GetSelectSqlString(JToken parentToken, string table_name)
    {
        string sqlSelect = "SELECT {1} FROM {0} ";
        List<string> arrFields = new List<string>(new string[] { "*" });
        if (parentToken["COLUMNS"] != null && parentToken["COLUMNS"] is JArray)
        {
            arrFields.Clear();
            foreach (var t in parentToken["COLUMNS"])
            {
                if (t["CONVERT"] == null)
                {
                    arrFields.Add(string.Format("[{0}] {1}", t.Value<string>("FIELD"), t["ALIAS"] != null ? " AS " + t.Value<string>("ALIAS") : ""));
                }
                else
                {
                    arrFields.Add(string.Format("{0}  AS {1}", t.Value<string>("CONVERT"), t["ALIAS"] != null ? t.Value<string>("ALIAS") : t.Value<string>("FIELD")));
                }
            }
        }
        return string.Format(sqlSelect, table_name, string.Join(",", arrFields.ToArray()));
    }

    /// <summary>
    /// Where拼接
    /// </summary>
    /// <param name="token"></param>
    /// <returns></returns>
    string GetWhereJointString(JToken token)
    {
        string joint = token["JOINT"].Value<string>().ToUpper();
        if (joint != "BETWEEN")
        {
            string field = token["FIELD"].Value<string>();
            if (!GetParamValues.ContainsKey(field))
            {
                return "";
            }

            var d = new ParamterSet().SetValueChain("EQUAL", "={0}").SetValueChain("UNEQUAL", "<>{0}")
               .SetValueChain("PREFIX", "LIKE {0}+'%'").SetValueChain("SUFFIX", "LIKE '%'+{0}").SetValueChain("CONTAIN", "LIKE '%'+{0}+'%'")
               .SetValueChain("GT", " >{0}").SetValueChain("LT", "<{0}").SetValueChain("ELT", " <={0}").SetValueChain("EGT", " >={0}");
            string formula = string.Format(d.GetValue<string>(joint), "@p" + field);
            return "[" + field + "]" + " " + formula;
        }
        else
        {
            string seg = "", seg1 = "", field = "", field1 = "";
            if (token["FIELD_GT"] != null)
            {
                field1 = token.Value<string>("FIELD_GT");
                seg1 = "[" + field1 + "]" + " >{0}";
            }
            else if (token["FIELD_EGT"] != null)
            {
                field1 = token.Value<string>("FIELD_EGT");
                seg1 = "[" + field1 + "]" + " >={0}";
            }

            if (token["FIELD_ELT"] != null)
            {
                field = token.Value<string>("FIELD_ELT");
                seg = "[" + field + "]" + " <={0}";
            }
            else if (token["FIELD_LT"] != null)
            {
                field = token.Value<string>("FIELD_LT");
                seg = "[" + field + "]" + " <{0}";
            }
            if (!GetParamValues.ContainsKey(field) || !GetParamValues.ContainsKey(field1))
            {
                return "";
            }

            return "(" + string.Format(seg, "@p" + field) + " AND " + string.Format(seg1, "@p" + field1) + ")";
        }
    }

    #endregion

    #region _private
    string GetRuntimeType()
    {
        string sp_name = GetRuntimeName();
        if (sp_name.StartsWith("!"))
        {
            return "sp";
        }
        else if (sp_name.StartsWith("@"))
        {
            return "sql";
        }
        else
        {
            return "table";
        }
    }

    string GetRuntimeName()
    {
        string sp_name = GetNode.Value<string>("SP_NAME").Trim();
        if (sp_name.StartsWith("!") || sp_name.StartsWith("@"))
        {
            return sp_name.Substring(1);
        }
        return sp_name;
    }
    
    string GetAliasNamed {
        get {
          
            return GetNode.Value<string>("ALIAS");
        }  
    }

    #endregion

    #region Import Properties
    public DataTable HostData
    {
        get;set;
    }

    public JToken HostJson
    {
        get;set;
    }

    public int SelectedEffectRows
    {
        get;set;
    }

    public Dictionary<string,object> GetParamValues
    {
        get; set;
    }

    public JObject GetRoot
    {
        get;set;
    }

    public JToken GetNode
    {
        get;set;
    }

    public JToken GetConfigNode {
        get
        {
            return GetRoot["config"].Value<JObject>();
        }
    }

     string GetDefaultDbName
    {
        get {
            return GetConfigNode.Value<string>("DEFAULT_DB_NAME");
        }
    }

    public string GetDbName
    {
        get {
            string db_name = "";
            if (GetNode["DB_NAME"] != null) {
                db_name = GetNode.Value<string>("DB_NAME");
            }
            if (string.IsNullOrWhiteSpace(db_name)) {
                db_name = GetDefaultDbName;
            }
            return db_name;
        }  
    }

# endregion
}



